/*
 * stressTester.c
 *
 *  Created on: Dec 25, 2011
 *      Author: shaohong
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <pthread.h>
#include "clientLogger.h"

#define NUM_OF_THREADS 10

/* the semaphore shared between the threads */
static sem_t loggingSemaphore;

void multiThreadedLogging();

static void * doLogging(void *arg) {

	// each thread do some 500 lines of logging
	for (int i = 0; i < 500; i++) {
		logDebugVarg("stressTester", "PID-%ld:ThreadID-%ld:logline-%d",
				getpid(), pthread_self(), i);
	}

	// each thred signal to the main thread that this thread has finished its logging
	sem_post(&loggingSemaphore);
	return (void*) (1);
}


int main(int argc, char ** argv) {

	// do some initialization of the logging
	initLogging();

	int numOfProcesses = 10;
	pid_t childpid;

	// let's create 10 child processes and each one tries to write 20 lines of logs.
	for(int i=0; i< numOfProcesses; i++) {
		childpid = fork();
		if (0 == childpid) {
			// this is the child process.
			// it shouldn't create new processes
			break;
		} else {
			continue;
		}
	}


	if (0 == childpid) {
		// each child process write 200 lines of logs
		for (int i = 0; i < 200; i++) {
//			fprintf(stderr, "PID:%d writing line %d", getpid(), i);
			logDebugVarg("stressTester ", "multiple processes logging, PID: %ld logline-%d", getpid(), i);
		}

		// child process returns
		return EXIT_SUCCESS;
	}

	// main process waits for all the children to finish their writings and then exit
	while(wait(NULL) > 0) ;

	// run a multi-threaded logging
	multiThreadedLogging();

	// do some clean up on the logging
	closeLogging();

	fprintf(stderr, "pid-%ld stress testing completed!\n", (long)getpid());

	return EXIT_SUCCESS;

}

/**
 * An multi-threaded logging where each thread spills its own logs
 * We use semaphores here to synchronize between the main threads and logging threads
 * REF: http://akomaenablog.blogspot.com/2008/03/semaphore-example-in-c.html
 */
void multiThreadedLogging() {

	pthread_t threads[NUM_OF_THREADS];

	// initialize the semaphore. The main thread will wait for the other threads to finish
	if (sem_init(&loggingSemaphore, 0, 0)) {
		perror("failed to init semaphore");
	}

	/* Assign args to a struct and start thread */
	for (int i = 0; i < NUM_OF_THREADS; i++) {
		pthread_create(&threads[i], NULL, doLogging, NULL);
	}

	/* main thread wait for the other threads to finish */
	for (int i = 0; i < NUM_OF_THREADS; i++) {

		sem_wait(&loggingSemaphore);
	}

}
